package cn.cas.mango.singlePass;

import cn.cas.mango.dbscan.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
public class SinglePass {
  private Map<String, Set<String>> inverted = new HashMap<>();
  private Map<String, Set<SinglePassData>> forward = new HashMap<>();

  private List<SinglePassData> original = new ArrayList<>();



  /**
   * 最开始的过滤，过滤那些没有任何关键词的数据
   * @param temp, 最原始的信息
   */
  private void initFilter(List<SinglePassData> temp) {
    original.addAll(temp.stream().filter(x->!x.getKeywords().isEmpty()).collect(Collectors.toList()));
  }
  public SinglePass(List<SinglePassData> original) {
    initFilter(original);
  }

  /**
   * 新的簇中心加入倒排
   * @param data, 新的簇中心
   */
  private void addAllKeywords(SinglePassData data) {
    Set<String> keywords = data.getKeywords();
    String id = data.getId();
    for (String string: keywords) {
      if (!inverted.containsKey(string)) {
        inverted.put(string, new LinkedHashSet<>());
      }
      inverted.get(string).add(id);
  }
  }

  public List<String> run(double param) {
    List<String> ret = new ArrayList<>();
    for (SinglePassData data: original) {
      String id = data.getId();
      Set<String> keywords = data.getKeywords();
      Set<String> candidates = new LinkedHashSet<>();
      for (String string: keywords) {
        if (inverted.containsKey(string)) {
          candidates.addAll(inverted.get(string));
        }
      }
      Set<String> nowKeywords = data.getKeywords();
      boolean breakFlag = false;
      for (String string: candidates) {
        SinglePassData first = forward.get(string).stream().limit(1).collect(Collectors.toList()).get(0);
        Set<String> firstKeywords = first.getKeywords();
        int interSize = Data.calInter(firstKeywords, nowKeywords).size();
        int unionSize = Data.calUnion(first.getKeywords(), data.getKeywords()).size();
        double sim = interSize * 1.0 / unionSize;
        if (sim >= param) {
          forward.get(string).add(data);
          breakFlag = true;
          break;
        }
      }
      if (!breakFlag) {
        forward.put(id, new LinkedHashSet<SinglePassData>(){{add(data);}});
        addAllKeywords(data);
      }
    }
    for (String string: forward.keySet()) {
      Set<SinglePassData> singlePassDataSet = forward.get(string);
      if (singlePassDataSet.size() != 1) {
        ret.addAll(singlePassDataSet.stream().map(x->x.getId()).collect(Collectors.toList()));
      }
    }
    log.info("now total: {}", ret.size());
    return ret;

  }
}
